home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gscie.c < prev    next >
C/C++ Source or Header  |  1997-04-24  |  41KB  |  1,200 lines

  1. /* Copyright (C) 1992, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gscie.c */
  20. /* CIE color rendering for Ghostscript */
  21. #include "math_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsstruct.h"
  25. #include "gsmatrix.h"            /* for gscolor2.h */
  26. #include "gxcspace.h"
  27. #include "gscolor2.h"            /* for gs_set/currentcolorrendering */
  28. #include "gscie.h"
  29. #include "gxarith.h"
  30. #include "gxdevice.h"            /* for gxcmap.h */
  31. #include "gxcmap.h"
  32. #include "gzstate.h"
  33.  
  34. /* Forward references */
  35. private void cie_joint_caches_init(P3(gx_cie_joint_caches *,
  36.   const gs_cie_common *, const gs_cie_render *));
  37. private void cie_joint_caches_complete(P3(gx_cie_joint_caches *,
  38.   const gs_cie_common *, const gs_cie_render *));
  39. private void near cie_mult3(P3(const gs_vector3 *, const gs_matrix3 *,
  40.   gs_vector3 *));
  41. private void near cie_matrix_mult3(P3(const gs_matrix3 *, const gs_matrix3 *,
  42.   gs_matrix3 *));
  43. private void near cie_invert3(P2(const gs_matrix3 *, gs_matrix3 *));
  44. private void near cie_matrix_init(P1(gs_matrix3 *));
  45.  
  46. #define set_restrict_index(i, v, n)\
  47.   if ( (uint)(i = (int)(v)) >= (n) )\
  48.     i = (i < 0 ? 0 : (n) - 1)
  49. #define restrict_index(v, n, itemp)\
  50.   ((uint)(itemp = (int)(v)) >= (n) ?\
  51.    (itemp < 0 ? 0 : (n) - 1) : itemp)
  52.  
  53. /* Compute a cache index as (vin - base) * factor. */
  54. /* vin, base, factor, and the result are cie_cached_values. */
  55. /* We know that the result doesn't exceed (gx_cie_cache_size - 1) << fbits. */
  56. #define lookup_index(vin, pcache, fbits)\
  57.   ((vin) <= (pcache)->vecs.params.base ? 0 :\
  58.    (vin) >= (pcache)->vecs.params.limit ? (gx_cie_cache_size - 1) << (fbits) :\
  59.    cie_cached_product2int( ((vin) - (pcache)->vecs.params.base),\
  60.                (pcache)->vecs.params.factor, fbits ))
  61. #define lookup_value(vin, pcache)\
  62.   ((pcache)->vecs.values[lookup_index(vin, pcache, 0)])
  63.  
  64. #define if_restrict(v, range)\
  65.   if ( (v) < (range).rmin ) v = (range).rmin;\
  66.   else if ( (v) > (range).rmax ) v = (range).rmax
  67.  
  68. /* Define the template for loading a cache. */
  69. /* If we had parameterized types, or a more flexible type system, */
  70. /* this could be done with a single procedure. */
  71. #define cie_cache_init3(pcache3, plp3, prange3, cname)\
  72.     gs_cie_cache_init(&(pcache3)->floats.params, &(plp3)[0], &(prange3)[0], cname);\
  73.     gs_cie_cache_init(&(pcache3)[1].floats.params, &(plp3)[1], &(prange3)[1], cname);\
  74.     gs_cie_cache_init(&(pcache3)[2].floats.params, &(plp3)[2], &(prange3)[2], cname)
  75. #define CIE_LOAD_CACHE3_BODY(pcache, domains, rprocs, pcie, cname)\
  76. {    int i, j;\
  77.     gs_for_loop_params lp[3];\
  78.     cie_cache_init3(pcache, lp, domains, cname);\
  79.     for ( i = 0; i < gx_cie_cache_size; i++ )\
  80.       for ( j = 0; j < 3; lp[j].init += lp[j].step, j++ )\
  81.         pcache[j].floats.values[i] =\
  82.           (*(rprocs)->procs[j])(lp[j].init, pcie);\
  83. }
  84.  
  85. /* ================ Color space definition ================ */
  86.  
  87. /* Allocator structure types */
  88. private_st_joint_caches();
  89. private_st_const_string();
  90. public_st_const_string_element();
  91. #define sptr ((gs_const_string *)vptr)
  92. private ENUM_PTRS_BEGIN(const_string_enum_ptrs) return 0;
  93.     case 0: *pep = (void *)sptr; return ptr_const_string_type;
  94. ENUM_PTRS_END
  95. private RELOC_PTRS_BEGIN(const_string_reloc_ptrs) {
  96.     gs_reloc_const_string(sptr, gcst);
  97. } RELOC_PTRS_END
  98. #undef sptr
  99.  
  100. /* Define the CIE color space types. */
  101. /* We use CIExxx rather than CIEBasedxxx in some places because */
  102. /* gcc under VMS only retains 23 characters of procedure names, */
  103. /* and DEC C truncates all identifiers at 31 characters. */
  104. private cs_proc_concrete_space(gx_concrete_space_CIE);
  105. cs_declare_procs(private, gx_concretize_CIEDEFG, gx_install_CIEDEFG,
  106.   gx_adjust_cspace_CIEDEFG,
  107.   gx_enum_ptrs_CIEDEFG, gx_reloc_ptrs_CIEDEFG);
  108. cs_declare_procs(private, gx_concretize_CIEDEF, gx_install_CIEDEF,
  109.   gx_adjust_cspace_CIEDEF,
  110.   gx_enum_ptrs_CIEDEF, gx_reloc_ptrs_CIEDEF);
  111. private cs_proc_remap_color(gx_remap_CIEABC);
  112. cs_declare_procs(private, gx_concretize_CIEABC, gx_install_CIEABC,
  113.   gx_adjust_cspace_CIEABC,
  114.   gx_enum_ptrs_CIEABC, gx_reloc_ptrs_CIEABC);
  115. cs_declare_procs(private, gx_concretize_CIEA, gx_install_CIEA,
  116.   gx_adjust_cspace_CIEA,
  117.   gx_enum_ptrs_CIEA, gx_reloc_ptrs_CIEA);
  118. const gs_color_space_type
  119.     gs_color_space_type_CIEDEFG =
  120.      { gs_color_space_index_CIEDEFG, 3, true,
  121.        gx_init_paint_3, gx_concrete_space_CIE,
  122.        gx_concretize_CIEDEFG, NULL,
  123.        gx_default_remap_color, gx_install_CIEDEFG,
  124.        gx_adjust_cspace_CIEDEFG, gx_no_adjust_color_count,
  125.        gx_enum_ptrs_CIEDEFG, gx_reloc_ptrs_CIEDEFG
  126.      },
  127.     gs_color_space_type_CIEDEF =
  128.      { gs_color_space_index_CIEDEF, 3, true,
  129.        gx_init_paint_3, gx_concrete_space_CIE,
  130.        gx_concretize_CIEDEF, NULL,
  131.        gx_default_remap_color, gx_install_CIEDEF,
  132.        gx_adjust_cspace_CIEDEF, gx_no_adjust_color_count,
  133.        gx_enum_ptrs_CIEDEF, gx_reloc_ptrs_CIEDEF
  134.      },
  135.     gs_color_space_type_CIEABC =
  136.      { gs_color_space_index_CIEABC, 3, true,
  137.        gx_init_paint_3, gx_concrete_space_CIE,
  138.        gx_concretize_CIEABC, NULL,
  139.        gx_remap_CIEABC, gx_install_CIEABC,
  140.        gx_adjust_cspace_CIEABC, gx_no_adjust_color_count,
  141.        gx_enum_ptrs_CIEABC, gx_reloc_ptrs_CIEABC
  142.      },
  143.     gs_color_space_type_CIEA =
  144.      { gs_color_space_index_CIEA, 1, true,
  145.        gx_init_paint_1, gx_concrete_space_CIE,
  146.        gx_concretize_CIEA, NULL,
  147.        gx_default_remap_color, gx_install_CIEA,
  148.        gx_adjust_cspace_CIEA, gx_no_adjust_color_count,
  149.        gx_enum_ptrs_CIEA, gx_reloc_ptrs_CIEA
  150.      };
  151.  
  152. /* GC procedures for CIE color spaces. */
  153. /* These have to come after the cs_declare_procs because of */
  154. /* a bug in the VAX C compiler. */
  155.  
  156. #define pcs ((gs_color_space *)vptr)
  157.  
  158. private ENUM_PTRS_BEGIN(gx_enum_ptrs_CIEDEFG) return 0;
  159.     ENUM_PTR(0, gs_color_space, params.defg);
  160. ENUM_PTRS_END
  161. private RELOC_PTRS_BEGIN(gx_reloc_ptrs_CIEDEFG) {
  162.     RELOC_PTR(gs_color_space, params.defg);
  163. } RELOC_PTRS_END
  164.  
  165. private ENUM_PTRS_BEGIN(gx_enum_ptrs_CIEDEF) return 0;
  166.     ENUM_PTR(0, gs_color_space, params.def);
  167. ENUM_PTRS_END
  168. private RELOC_PTRS_BEGIN(gx_reloc_ptrs_CIEDEF) {
  169.     RELOC_PTR(gs_color_space, params.def);
  170. } RELOC_PTRS_END
  171.  
  172. private ENUM_PTRS_BEGIN(gx_enum_ptrs_CIEABC) return 0;
  173.     ENUM_PTR(0, gs_color_space, params.abc);
  174. ENUM_PTRS_END
  175. private RELOC_PTRS_BEGIN(gx_reloc_ptrs_CIEABC) {
  176.     RELOC_PTR(gs_color_space, params.abc);
  177. } RELOC_PTRS_END
  178.  
  179. private ENUM_PTRS_BEGIN(gx_enum_ptrs_CIEA) return 0;
  180.     ENUM_PTR(0, gs_color_space, params.a);
  181. ENUM_PTRS_END
  182. private RELOC_PTRS_BEGIN(gx_reloc_ptrs_CIEA) {
  183.     RELOC_PTR(gs_color_space, params.a);
  184. } RELOC_PTRS_END
  185.  
  186. #undef pcs
  187.  
  188. /* ------ Default values for CIE dictionary elements ------ */
  189.  
  190. /* Default transformation procedures. */
  191.  
  192. private float
  193. a_identity(floatp in, const gs_cie_a *pcie)
  194. {    return in;
  195. }
  196. private float
  197. abc_identity(floatp in, const gs_cie_abc *pcie)
  198. {    return in;
  199. }
  200. private float
  201. def_identity(floatp in, const gs_cie_def *pcie)
  202. {    return in;
  203. }
  204. private float
  205. defg_identity(floatp in, const gs_cie_defg *pcie)
  206. {    return in;
  207. }
  208. private float
  209. common_identity(floatp in, const gs_cie_common *pcie)
  210. {    return in;
  211. }
  212. private float
  213. render_identity(floatp in, const gs_cie_render *pcie)
  214. {    return in;
  215. }
  216. private float
  217. tpqr_identity(floatp in, const gs_cie_wbsd *pwbsd, const gs_cie_render *pcie)
  218. {    return in;
  219. }
  220. private frac
  221. render_table_identity(byte in, const gs_cie_render *pcie)
  222. {    return byte2frac(in);
  223. }
  224.  
  225. /* Default vectors and matrices. */
  226.  
  227. const gs_range3 Range3_default = { {{0,1}, {0,1}, {0,1}} };
  228. const gs_range4 Range4_default = { {{0,1}, {0,1}, {0,1}, {0,1}} };
  229. const gs_cie_defg_proc4 DecodeDEFG_default =
  230.  { { defg_identity, defg_identity, defg_identity, defg_identity } };
  231. const gs_cie_def_proc3 DecodeDEF_default =
  232.  { { def_identity, def_identity, def_identity } };
  233. const gs_cie_abc_proc3 DecodeABC_default =
  234.  { { abc_identity, abc_identity, abc_identity } };
  235. const gs_cie_common_proc3 DecodeLMN_default =
  236.  { { common_identity, common_identity, common_identity } };
  237. const gs_matrix3 Matrix3_default = { {1,0,0}, {0,1,0}, {0,0,1}, 1 /*true*/ };
  238. const gs_range RangeA_default = {0,1};
  239. const gs_cie_a_proc DecodeA_default = a_identity;
  240. const gs_vector3 MatrixA_default = { 1, 1, 1 };
  241. const gs_vector3 BlackPoint_default = { 0, 0, 0 };
  242. const gs_cie_render_proc3 Encode_default =
  243.  { { render_identity, render_identity, render_identity } };
  244. const gs_cie_transform_proc3 TransformPQR_default =
  245.  { { tpqr_identity, tpqr_identity, tpqr_identity } };
  246. const gs_cie_render_table_procs RenderTableT_default =
  247.  { { render_table_identity, render_table_identity, render_table_identity,
  248.      render_table_identity
  249.  } };
  250.  
  251. /* ------ Adjust reference counts for a CIE color space ------ */
  252.  
  253. private void
  254. gx_adjust_cspace_CIEDEFG(const gs_color_space *pcs, gs_memory_t *mem,
  255.   int delta)
  256. {    rc_adjust_const(pcs->params.defg, delta, "gx_adjust_cspace_CIEDEFG");
  257. }
  258.  
  259. private void
  260. gx_adjust_cspace_CIEDEF(const gs_color_space *pcs, gs_memory_t *mem,
  261.   int delta)
  262. {    rc_adjust_const(pcs->params.def, delta, "gx_adjust_cspace_CIEDEF");
  263. }
  264.  
  265. private void
  266. gx_adjust_cspace_CIEABC(const gs_color_space *pcs, gs_memory_t *mem,
  267.   int delta)
  268. {    rc_adjust_const(pcs->params.abc, delta, "gx_adjust_cspace_CIEABC");
  269. }
  270.  
  271. private void
  272. gx_adjust_cspace_CIEA(const gs_color_space *pcs, gs_memory_t *mem,
  273.   int delta)
  274. {    rc_adjust_const(pcs->params.a, delta, "gx_adjust_cspace_CIEA");
  275. }
  276.  
  277. /* ================ Table setup ================ */
  278.  
  279. /* ------ Install a CIE color space ------ */
  280.  
  281. private int cie_load_common_cache(P3(gs_cie_common *, gs_state *,
  282.   client_name_t));
  283. private void near cie_cache_mult(P3(gx_cie_vector_cache *, const gs_vector3 *,
  284.                     const cie_cache_floats *));
  285. private bool near cie_cache_mult3(P2(gx_cie_vector_cache *,
  286.                      const gs_matrix3 *));
  287.  
  288. private int
  289. gx_install_CIEDEFG(gs_color_space *pcs, gs_state *pgs)
  290. {    /****** NOT IMPLEMENTED YET ******/
  291.     return_error(gs_error_undefined);
  292. }
  293.  
  294. private int
  295. gx_install_CIEDEF(gs_color_space *pcs, gs_state *pgs)
  296. {    /****** NOT IMPLEMENTED YET ******/
  297.     return_error(gs_error_undefined);
  298. }
  299.  
  300. private int
  301. gx_install_CIEABC(gs_color_space *pcs, gs_state *pgs)
  302. {    gs_cie_abc *pcie = pcs->params.abc;
  303.     cie_matrix_init(&pcie->MatrixABC);
  304.     CIE_LOAD_CACHE3_BODY(pcie->caches.DecodeABC, pcie->RangeABC.ranges,
  305.                  &pcie->DecodeABC, pcie, "DecodeABC");
  306.     gs_cie_abc_complete(pcie);
  307.     return cie_load_common_cache(&pcie->common, pgs, "gx_install_CIEABC");
  308. }
  309.  
  310. private int
  311. gx_install_CIEA(gs_color_space *pcs, gs_state *pgs)
  312. {    gs_cie_a *pcie = pcs->params.a;
  313.     int i;
  314.     gs_for_loop_params lp;
  315.     float in;
  316.     gs_cie_cache_init(&pcie->caches.DecodeA.floats.params, &lp,
  317.               &pcie->RangeA, "DecodeA");
  318.     for ( i = 0, in = lp.init; i < gx_cie_cache_size; in += lp.step, i++ )
  319.       pcie->caches.DecodeA.floats.values[i] =
  320.         (*pcie->DecodeA)(in, pcie);
  321.     gs_cie_a_complete(pcie);
  322.     return cie_load_common_cache(&pcie->common, pgs, "gx_install_CIEA");
  323. }
  324.  
  325. /* Load the common caches when installing the color space. */
  326. private int
  327. cie_load_common_cache(gs_cie_common *pcie, gs_state *pgs, client_name_t cname)
  328. {    gx_cie_joint_caches *pjc;
  329.  
  330.     cie_matrix_init(&pcie->MatrixLMN);
  331.     CIE_LOAD_CACHE3_BODY(pcie->caches.DecodeLMN, pcie->RangeLMN.ranges,
  332.                  &pcie->DecodeLMN, pcie, "DecodeLMN")
  333.     if ( pgs->cie_render == 0 )
  334.       return 0;
  335.     pjc = gx_currentciecaches(pgs);
  336.     if ( pjc == 0 )
  337.       return_error(gs_error_VMerror);
  338.     cie_joint_caches_init(pjc, pcie, pgs->cie_render);
  339.     cie_joint_caches_complete(pjc, pcie, pgs->cie_render);
  340.     return 0;
  341. }
  342.  
  343. /* Complete loading a CIEBasedABC color space. */
  344. /* This routine is not idempotent. */
  345. void
  346. gs_cie_abc_complete(gs_cie_abc *pcie)
  347. {    pcie->caches.skipABC =
  348.       cie_cache_mult3(pcie->caches.DecodeABC, &pcie->MatrixABC);
  349. }
  350.  
  351. /* Complete loading a CIEBasedA color space. */
  352. /* This routine is not idempotent. */
  353. void
  354. gs_cie_a_complete(gs_cie_a *pcie)
  355. {    cie_cache_mult(&pcie->caches.DecodeA, &pcie->MatrixA,
  356.                &pcie->caches.DecodeA.floats);
  357. }
  358.  
  359. /* Convert a scalar cache to a vector cache by multiplying */
  360. /* the scalar values by a vector. */
  361. private void near
  362. cie_cache_mult(gx_cie_vector_cache *pcache, const gs_vector3 *pvec,
  363.   const cie_cache_floats *pcf)
  364. {    int i;
  365.     cie_vector_cache_params params;
  366.     params.is_identity = pcf->params.is_identity;
  367.     params.base = float2cie_cached(pcf->params.base);
  368.     params.factor = float2cie_cached(pcf->params.factor);
  369.     params.limit =
  370.       float2cie_cached((gx_cie_cache_size - 1) / pcf->params.factor +
  371.                pcf->params.base);
  372.     /* Loop from top to bottom so that we don't */
  373.     /* overwrite elements before they're used, */
  374.     /* in case pcf is an alias for pcache->floats. */
  375.     for ( i = gx_cie_cache_size; --i >= 0; )
  376.       {    float f = pcf->values[i];
  377.         pcache->vecs.values[i].u = float2cie_cached(f * pvec->u);
  378.         pcache->vecs.values[i].v = float2cie_cached(f * pvec->v);
  379.         pcache->vecs.values[i].w = float2cie_cached(f * pvec->w);
  380.       }
  381.     pcache->vecs.params = params;
  382. }
  383. /* Convert 3 scalar caches to vector caches by multiplying by a matrix. */
  384. /* Return true iff the resulting cache is an identity transformation. */
  385. private bool near
  386. cie_cache_mult3(gx_cie_vector_cache *pc /*[3]*/, const gs_matrix3 *pmat)
  387. {    cie_cache_mult(pc, &pmat->cu, &pc->floats);
  388.     cie_cache_mult(pc + 1, &pmat->cv, &pc[1].floats);
  389.     cie_cache_mult(pc + 2, &pmat->cw, &pc[2].floats);
  390.     return pmat->is_identity & pc[0].vecs.params.is_identity &
  391.        pc[1].vecs.params.is_identity & pc[2].vecs.params.is_identity;
  392. }
  393.  
  394. /* ------ Install a rendering dictionary ------ */
  395.  
  396. /* setcolorrendering */
  397. int
  398. gs_setcolorrendering(gs_state *pgs, gs_cie_render *pcie)
  399. {    int code = gs_cie_render_init(pcie);
  400.     if ( code < 0 )
  401.       return code;
  402.     rc_assign(pgs->cie_render, pcie, "gs_setcolorrendering");
  403.     /* Load the caches. */
  404.     CIE_LOAD_CACHE3_BODY(pcie->caches.EncodeLMN, pcie->DomainLMN.ranges,
  405.                  &pcie->EncodeLMN, pcie, "EncodeLMN");
  406.     CIE_LOAD_CACHE3_BODY(pcie->caches.EncodeABC, pcie->DomainABC.ranges,
  407.                  &pcie->EncodeABC, pcie, "EncodeABC");
  408.     if ( pcie->RenderTable.lookup.table != 0 )
  409.       { int i, j, m = pcie->RenderTable.lookup.m;
  410.         gs_for_loop_params flp;
  411.         for ( j = 0; j < m; j++ )
  412.           gs_cie_cache_init(&pcie->caches.RenderTableT[j].fracs.params,
  413.                 &flp, &Range3_default.ranges[0],
  414.                 "RenderTableT");
  415.         /****** ASSUMES gx_cie_cache_size >= 256 ******/
  416.         for ( i = 0; i < 256; i++ )
  417.           for ( j = 0; j < m; j++ )
  418.         pcie->caches.RenderTableT[j].fracs.values[i] =
  419.           (*pcie->RenderTable.T.procs[j])((byte)i, pcie);
  420.       }
  421.     code = gs_cie_render_complete(pcie);
  422.     if ( code < 0 )
  423.       return code;
  424.     /* Initialize the joint caches if needed. */
  425.     gs_cie_cs_complete(pgs, true);
  426.     gx_unset_dev_color(pgs);
  427.     return code;
  428. }
  429.  
  430. /* currentcolorrendering */
  431. const gs_cie_render *
  432. gs_currentcolorrendering(const gs_state *pgs)
  433. {    return pgs->cie_render;
  434. }
  435.  
  436. /* Unshare (allocating if necessary) the joint caches. */
  437. gx_cie_joint_caches *
  438. gx_currentciecaches(gs_state *pgs)
  439. {    rc_unshare_struct(pgs->cie_joint_caches, gx_cie_joint_caches,
  440.               &st_joint_caches, pgs->memory,
  441.               return 0, "gx_currentciecaches");
  442.     return pgs->cie_joint_caches;
  443. }
  444.  
  445. /* ------ Compute the parameters for loading a cache. ------ */
  446. /* Sets base and factor. */
  447.  
  448. void
  449. gs_cie_cache_init(cie_cache_params *pcache, gs_for_loop_params *pflp,
  450.   const gs_range *domain, client_name_t cname)
  451. {    /*
  452.      * We need to map the values in the range
  453.      * [domain->rmin..domain->rmax].  However, if neither rmin
  454.      * nor rmax is zero and the function is non-linear,
  455.      * this can lead to anomalies at zero, which is the
  456.      * default value for CIE colors.  The "correct" way to
  457.      * approach this is to run the mapping functions on demand,
  458.      * but we don't want to deal with the complexities of the
  459.      * callbacks this would involve (especially in the middle of
  460.      * rendering images); instead, we adjust the range so that zero
  461.      * maps precisely to a cache slot.  Define:
  462.      *    a = domain->rmin;
  463.      *    b = domain->rmax;
  464.      *    R = b - a;
  465.      *    N = gx_cie_cache_size - 1;
  466.      *    f(v) = N(v-a)/R;
  467.      *    x = f(0).
  468.      * If x is not an integer, we can either increase b or
  469.      * decrease a to make it one.  In the former case, compute:
  470.      *    Kb = floor(x); R'b = N(0-a)/Kb; b' = a + R'b.
  471.      * In the latter case, compute:
  472.      *    Ka = ceiling(x-N); R'a = N(0-b)/Ka; a' = b - R'a.
  473.      * We choose whichever method stretches the range the least,
  474.      * i.e., the one whose R' value (R'a or R'b) is smaller.
  475.      */
  476.     double a = domain->rmin, b = domain->rmax;
  477.     double R = b - a;
  478. #define N (gx_cie_cache_size - 1)
  479.     double delta;
  480.     /* Adjust the range if necessary. */
  481.     if ( a < 0 && b >= 0 )
  482.       {    double x = -N * a / R;    /* must be > 0 */
  483.         double Kb = floor(x);        /* must be >= 0 */
  484.         double Ka = ceil(x) - N;    /* must be <= 0 */
  485.         if ( Kb == 0 || (Ka != 0 && -b / Ka < -a / Kb) )    /* use R'a */
  486.           R = -N * b / Ka, a = b - R;
  487.         else            /* use R'b */
  488.           R = -N * a / Kb, b = a + R;
  489.       }
  490.     delta = R / N;
  491. #ifdef CIE_CACHE_INTERPOLATE
  492.     pcache->base = a;        /* no rounding */
  493. #else
  494.     pcache->base = a - delta / 2;    /* so lookup will round */
  495. #endif
  496.     pcache->factor = (delta == 0 ? 0 : N / R);
  497.     if_debug4('c', "[c]cache %s 0x%lx base=%g, factor=%g\n",
  498.           (const char *)cname, (ulong)pcache,
  499.           pcache->base, pcache->factor);
  500.     pflp->init = a;
  501.     pflp->step = delta;
  502.     pflp->limit = b + delta / 2;
  503. }
  504.  
  505. /* ------ Complete a rendering structure ------ */
  506.  
  507. /* Compute values derived from the rendering structure parameters */
  508. /* other than the cached procedure values.  This routine is idempotent. */
  509. private void near cie_transform_range3(P3(const gs_range3 *,
  510.   const gs_matrix3 *, gs_range3 *));
  511. int
  512. gs_cie_render_init(gs_cie_render *pcie)
  513. {    gs_matrix3 PQR_inverse;
  514.     cie_matrix_init(&pcie->MatrixLMN);
  515.     cie_matrix_init(&pcie->MatrixABC);
  516.     cie_matrix_init(&pcie->MatrixPQR);
  517.     cie_invert3(&pcie->MatrixPQR, &PQR_inverse);
  518.     cie_matrix_mult3(&pcie->MatrixLMN, &PQR_inverse,
  519.              &pcie->MatrixPQR_inverse_LMN);
  520.     cie_transform_range3(&pcie->RangePQR, &pcie->MatrixPQR_inverse_LMN,
  521.                  &pcie->DomainLMN);
  522.     cie_transform_range3(&pcie->RangeLMN, &pcie->MatrixABC,
  523.                  &pcie->DomainABC);
  524.     cie_mult3(&pcie->points.WhitePoint, &pcie->MatrixPQR, &pcie->wdpqr);
  525.     cie_mult3(&pcie->points.BlackPoint, &pcie->MatrixPQR, &pcie->bdpqr);
  526.     return 0;
  527. }
  528.  
  529. /* Transform a set of ranges. */
  530. private void near
  531. cie_transform_range(const gs_range3 *in, floatp mu, floatp mv, floatp mw,
  532.   gs_range *out)
  533. {    float umin = mu * in->ranges[0].rmin,
  534.       umax = mu * in->ranges[0].rmax;
  535.     float vmin = mv * in->ranges[1].rmin,
  536.       vmax = mv * in->ranges[1].rmax;
  537.     float wmin = mw * in->ranges[2].rmin,
  538.       wmax = mw * in->ranges[2].rmax;
  539.     float temp;
  540. #define swap(x, y) temp = x, x = y, y = temp
  541.  
  542.     if ( umin > umax ) swap(umin, umax);
  543.     if ( vmin > vmax ) swap(vmin, vmax);
  544.     if ( wmin > wmax ) swap(wmin, wmax);
  545.     out->rmin = umin + vmin + wmin;
  546.     out->rmax = umax + vmax + wmax;
  547. #undef swap
  548. }
  549. private void near
  550. cie_transform_range3(const gs_range3 *in, const gs_matrix3 *mat,
  551.   gs_range3 *out)
  552. {    cie_transform_range(in, mat->cu.u, mat->cv.u, mat->cw.u,
  553.                 &out->ranges[0]);
  554.     cie_transform_range(in, mat->cu.v, mat->cv.v, mat->cw.v,
  555.                 &out->ranges[1]);
  556.     cie_transform_range(in, mat->cu.w, mat->cv.w, mat->cw.w,
  557.                 &out->ranges[2]);
  558. }
  559.  
  560. /* Complete the loading of the rendering caches. */
  561. /* Note that this routine may make non-idempotent changes to */
  562. /* the values in the caches. */
  563. private void near cie_cache_restrict(P2(cie_cache_floats *, const gs_range *));
  564. #define cie_cache_restrict3(pcache3, pr3)\
  565.     cie_cache_restrict(&(pcache3)[0].floats, &(pr3)->ranges[0]);\
  566.     cie_cache_restrict(&(pcache3)[1].floats, &(pr3)->ranges[1]);\
  567.     cie_cache_restrict(&(pcache3)[2].floats, &(pr3)->ranges[2])
  568. int
  569. gs_cie_render_complete(gs_cie_render *pcie)
  570. {    /* Since range restriction happens immediately after */
  571.     /* the cache lookup, we can save a step by restricting */
  572.     /* the values in the cache entries. */
  573.     cie_cache_restrict3(pcie->caches.EncodeLMN, &pcie->RangeLMN);
  574.     cie_cache_restrict3(pcie->caches.EncodeABC, &pcie->RangeABC);
  575.     /* If there is no lookup table, we want the final ABC values */
  576.     /* to be fracs; if there is a table, we want them to be */
  577.     /* appropriately scaled ints. */
  578.     pcie->MatrixABCEncode = pcie->MatrixABC;
  579.       {    int c;
  580.         double f;
  581.         for ( c = 0; c < 3; c++ )
  582.           {    gx_cie_scalar_cache *pcache =
  583.               &pcie->caches.EncodeABC[c];
  584.             if ( pcie->RenderTable.lookup.table == 0 )
  585.             {    cie_cache_restrict(&pcache->floats,
  586.                            &Range3_default.ranges[0]);
  587.                 gs_cie_cache_to_fracs(pcache);
  588.                 pcache->fracs.params.is_identity = false;
  589.             }
  590.             else
  591.             {    int i;
  592.                 int n = pcie->RenderTable.lookup.dims[c];
  593. #ifdef CIE_RENDER_TABLE_INTERPOLATE
  594. #  define scale_index(f, n, itemp)\
  595.      restrict_index(f * (1 << _cie_interpolate_bits),\
  596.             (n) << _cie_interpolate_bits, itemp)
  597. #else
  598.                 int m = pcie->RenderTable.lookup.m;
  599.                 int k =
  600.                   (c == 0 ? 1 : c == 1 ?
  601.                    m * pcie->RenderTable.lookup.dims[2] : m);
  602. #  define scale_index(f, n, itemp)\
  603.      (restrict_index(f, n, itemp) * k)
  604. #endif
  605.                 const gs_range *prange =
  606.                   pcie->RangeABC.ranges + c;
  607.                 /* Loop from top to bottom so that we don't */
  608.                 /* overwrite elements before they're used. */
  609.                 for ( i = gx_cie_cache_size; --i >= 0; )
  610.                 {    float v =
  611.                       (pcache->floats.values[i] -
  612.                        prange->rmin) * (n - 1) /
  613.                       (prange->rmax - prange->rmin)
  614. #ifndef CIE_RENDER_TABLE_INTERPOLATE
  615.                         + 0.5
  616. #endif
  617.                           ;
  618.                     int itemp;
  619.  
  620.                     if_debug5('c',
  621.                       "[c]cache[%d][%d] = %g => %g => %d\n",
  622.                       c, i, pcache->floats.values[i], v,
  623.                       scale_index(v, n, itemp));
  624.                     pcache->ints.values[i] =
  625.                       scale_index(v, n, itemp);
  626.                 }
  627.                 pcache->ints.params = pcache->floats.params;    /* (not necessary) */
  628.                 pcache->ints.params.is_identity = false;
  629. #undef scale_index
  630.             }
  631.           }
  632.         /* Fold the scaling of the EncodeABC cache index */
  633.         /* into MatrixABC. */
  634. #define mabc(i, t)\
  635.   f = pcie->caches.EncodeABC[i].floats.params.factor;\
  636.   pcie->MatrixABCEncode.cu.t *= f;\
  637.   pcie->MatrixABCEncode.cv.t *= f;\
  638.   pcie->MatrixABCEncode.cw.t *= f;\
  639.   pcie->EncodeABC_base[i] =\
  640.     float2cie_cached(pcie->caches.EncodeABC[i].floats.params.base * f)
  641.         mabc(0, u);
  642.         mabc(1, v);
  643.         mabc(2, w);
  644.         pcie->MatrixABCEncode.is_identity = 0;
  645.       }
  646. #undef mabc
  647.     cie_cache_mult3(pcie->caches.EncodeLMN, &pcie->MatrixABCEncode);
  648.     return 0;
  649. }
  650.  
  651. /* Apply a range restriction to one cache or 3 caches. */
  652. private void near
  653. cie_cache_restrict(cie_cache_floats *pcache, const gs_range *prange)
  654. {    int i;
  655.     for ( i = 0; i < gx_cie_cache_size; i++ )
  656.       if_restrict(pcache->values[i], *prange);
  657. }
  658.  
  659. /* Convert a cache from floats to fracs. */
  660. void
  661. gs_cie_cache_to_fracs(gx_cie_scalar_cache *pcache)
  662. {    int i;
  663.     /* Loop from bottom to top so that we don't */
  664.     /* overwrite elements before they're used. */
  665.     for ( i = 0; i < gx_cie_cache_size; ++i )
  666.       pcache->fracs.values[i] = float2frac(pcache->floats.values[i]);
  667.     pcache->fracs.params = pcache->floats.params;    /* (not necessary) */
  668. }
  669.  
  670. /* ------ Fill in the joint cache ------ */
  671.  
  672. /* If the current color space is a CIE space, or has a CIE base space, */
  673. /* return a pointer to the common part of the space; otherwise return 0. */
  674. const gs_cie_common *
  675. gs_cie_cs_common(gs_state *pgs)
  676. {    const gs_color_space *pcs = pgs->color_space;
  677.  
  678. sw:    switch ( pcs->type->index )
  679.       {
  680.       case gs_color_space_index_CIEABC:
  681.         return &pcs->params.abc->common;
  682.       case gs_color_space_index_CIEA:
  683.         return &pcs->params.a->common;
  684.       case gs_color_space_index_Separation:
  685.         pcs = (const gs_color_space *)&pcs->params.separation.alt_space;
  686.         goto sw;
  687.       case gs_color_space_index_Indexed:
  688.         pcs = gs_color_space_indexed_base_space(pcs);
  689.         goto sw;
  690.       case gs_color_space_index_Pattern:
  691.         /****** WHAT? ******/
  692.       default:
  693.         return 0;
  694.       }
  695. }
  696.  
  697. /* Finish loading the joint caches for the current color space. */
  698. void
  699. gs_cie_cs_complete(gs_state *pgs, bool init)
  700. {    const gs_cie_common *common = gs_cie_cs_common(pgs);
  701.  
  702.     if ( common )
  703.       { if ( init )
  704.           cie_joint_caches_init(pgs->cie_joint_caches, common,
  705.                     pgs->cie_render);
  706.         cie_joint_caches_complete(pgs->cie_joint_caches, common,
  707.                       pgs->cie_render);
  708.       }
  709. }
  710.  
  711. /* Compute values derived from the color space and rendering parameters */
  712. /* other than the cached procedure values.  This routine is idempotent. */
  713. private void
  714. cie_joint_caches_init(gx_cie_joint_caches *pjc,
  715.   const gs_cie_common *pcie, const gs_cie_render *pcier)
  716. {    pjc->points_sd.ws.xyz = pcie->points.WhitePoint;
  717.     cie_mult3(&pjc->points_sd.ws.xyz, &pcier->MatrixPQR,
  718.           &pjc->points_sd.ws.pqr);
  719.     pjc->points_sd.bs.xyz = pcie->points.BlackPoint;
  720.     cie_mult3(&pjc->points_sd.bs.xyz, &pcier->MatrixPQR,
  721.           &pjc->points_sd.bs.pqr);
  722.     pjc->points_sd.wd.xyz = pcier->points.WhitePoint;
  723.     pjc->points_sd.wd.pqr = pcier->wdpqr;
  724.     pjc->points_sd.bd.xyz = pcier->points.BlackPoint;
  725.     pjc->points_sd.bd.pqr = pcier->bdpqr;
  726.     cie_matrix_mult3(&pcier->MatrixPQR, &pcie->MatrixLMN,
  727.              &pjc->MatrixLMN_PQR);
  728.     /* Load the TransformPQR caches. */
  729.     { int i, j;
  730.       gs_for_loop_params lp[3];
  731.       cie_cache_init3(pjc->TransformPQR, lp, pcier->RangePQR.ranges,
  732.               "TransformPQR");
  733.       for ( i = 0; i < gx_cie_cache_size; i++ )
  734.         for ( j = 0; j < 3; lp[j].init += lp[j].step, j++ )
  735.           pjc->TransformPQR[j].floats.values[i] =
  736.         (*pcier->TransformPQR.procs[j])(lp[j].init, &pjc->points_sd, pcier);
  737.     }
  738. }
  739.  
  740. /* Complete the loading of the joint caches.  Note that this routine */
  741. /* may make non-idempotent changes to the values in the caches. */
  742. private void
  743. cie_joint_caches_complete(gx_cie_joint_caches *pjc,
  744.   const gs_cie_common *pcie, const gs_cie_render *pcier)
  745. {    int j;
  746.     cie_cache_restrict3(pjc->TransformPQR, &pcier->RangePQR);
  747.     for ( j = 0; j < 3; j++ )
  748.       cie_cache_mult(&pjc->DecodeLMN[j],
  749.              &pjc->MatrixLMN_PQR.cu + j,
  750.              &pcie->caches.DecodeLMN[j].floats);
  751.     pjc->skipLMN = pjc->MatrixLMN_PQR.is_identity &
  752.       pjc->DecodeLMN[0].vecs.params.is_identity &
  753.       pjc->DecodeLMN[1].vecs.params.is_identity &
  754.       pjc->DecodeLMN[2].vecs.params.is_identity;
  755.     pjc->skipPQR =
  756.       cie_cache_mult3(pjc->TransformPQR, &pcier->MatrixPQR_inverse_LMN);
  757. }
  758.  
  759. /* ================ Color rendering (using the caches) ================ */
  760.  
  761. private int near cie_remap_finish(P3(const cie_cached_vector3 *,
  762.                      frac *, const gs_imager_state *));
  763. private void near cie_lookup_mult3(P2(cie_cached_vector3 *,
  764.                       const gx_cie_vector_cache *));
  765. #ifdef DEBUG
  766. private void near
  767. cie_lookup_map3(cie_cached_vector3 *pvec,
  768.   const gx_cie_vector_cache *pc /*[3]*/, const char _ds *cname)
  769. {    if_debug5('c', "[c]lookup %s 0x%lx [%g %g %g]\n",
  770.           (const char *)cname, (ulong)pc,
  771.           cie_cached2float(pvec->u), cie_cached2float(pvec->v),
  772.           cie_cached2float(pvec->w));
  773.     cie_lookup_mult3(pvec, pc);
  774.     if_debug3('c', "        =[%g %g %g]\n",
  775.           cie_cached2float(pvec->u), cie_cached2float(pvec->v),
  776.           cie_cached2float(pvec->w));
  777. }
  778. #else
  779. #  define cie_lookup_map3(pvec, pc, cname) cie_lookup_mult3(pvec, pc)
  780. #endif
  781.  
  782. /* Determine the concrete space underlying a CIEBased space. */
  783. private const gs_color_space *
  784. gx_concrete_space_CIE(const gs_color_space *pcs, const gs_imager_state *pis)
  785. {    const gs_cie_render *pcie = pis->cie_render;
  786.     if ( pcie == 0 || pcie->RenderTable.lookup.table == 0 ||
  787.          pcie->RenderTable.lookup.m == 3
  788.        )
  789.       return gs_color_space_DeviceRGB();
  790.     else                /* pcie->RenderTable.lookup.m == 4 */
  791.       return gs_color_space_DeviceCMYK();
  792. }
  793.  
  794. /* Render a CIEBasedDEFG color. */
  795. private int
  796. gx_concretize_CIEDEFG(const gs_client_color *pc, const gs_color_space *pcs,
  797.   frac *pconc, const gs_imager_state *pis)
  798. {    /****** NOT IMPLEMENTED YET ******/
  799.     return_error(gs_error_undefined);
  800. }
  801.  
  802. /* Render a CIEBasedDEF color. */
  803. private int
  804. gx_concretize_CIEDEF(const gs_client_color *pc, const gs_color_space *pcs,
  805.   frac *pconc, const gs_imager_state *pis)
  806. {    /****** NOT IMPLEMENTED YET ******/
  807.     return_error(gs_error_undefined);
  808. }
  809.  
  810. /* Render a CIEBasedABC color. */
  811. /* We provide both remap and concretize, but only the former */
  812. /* needs to be efficient. */
  813. private int
  814. gx_remap_CIEABC(const gs_client_color *pc, const gs_color_space *pcs,
  815.   gx_device_color *pdc, const gs_imager_state *pis, gx_device *dev,
  816.   gs_color_select_t select)
  817. {    frac conc[4];
  818.     const gs_cie_abc *pcie = pcs->params.abc;
  819.     cie_cached_vector3 vec3;
  820.  
  821.     if_debug3('c', "[c]remap CIEABC [%g %g %g]\n",
  822.           pc->paint.values[0], pc->paint.values[1],
  823.           pc->paint.values[2]);
  824.     vec3.u = float2cie_cached(pc->paint.values[0]);
  825.     vec3.v = float2cie_cached(pc->paint.values[1]);
  826.     vec3.w = float2cie_cached(pc->paint.values[2]);
  827.  
  828.     /* Apply DecodeABC and MatrixABC. */
  829. #define vabc vec3
  830. #define vlmn vec3
  831.     if ( !pcie->caches.skipABC )
  832.       cie_lookup_map3(&vabc /*&vlmn*/, &pcie->caches.DecodeABC[0],
  833.               "Decode/MatrixABC");
  834. #undef vabc
  835.     switch ( cie_remap_finish(&vlmn, conc, pis) )
  836.       {
  837.       case 3:
  838.         if_debug3('c', "[c]=RGB [%g %g %g]\n",
  839.               frac2float(conc[0]), frac2float(conc[1]),
  840.                 frac2float(conc[2]));
  841.         gx_remap_concrete_rgb(conc[0], conc[1], conc[2], pdc, pis,
  842.                       dev, select);
  843.         return 0;
  844.       case 4:
  845.         if_debug4('c', "[c]=CMYK [%g %g %g %g]\n",
  846.               frac2float(conc[0]), frac2float(conc[1]),
  847.                 frac2float(conc[2]), frac2float(conc[3]));
  848.         gx_remap_concrete_cmyk(conc[0], conc[1], conc[2], conc[3],
  849.                        pdc, pis, dev, select);
  850.         return 0;
  851.       }
  852.     /* Can't happen. */
  853.     return_error(gs_error_unknownerror);
  854. #undef vlmn
  855. }
  856. private int
  857. gx_concretize_CIEABC(const gs_client_color *pc, const gs_color_space *pcs,
  858.   frac *pconc, const gs_imager_state *pis)
  859. {    const gs_cie_abc *pcie = pcs->params.abc;
  860.     cie_cached_vector3 vec3;
  861.  
  862.     if_debug3('c', "[c]concretize CIEABC [%g %g %g]\n",
  863.           pc->paint.values[0], pc->paint.values[1],
  864.           pc->paint.values[2]);
  865.     vec3.u = float2cie_cached(pc->paint.values[0]);
  866.     vec3.v = float2cie_cached(pc->paint.values[1]);
  867.     vec3.w = float2cie_cached(pc->paint.values[2]);
  868. #define vabc vec3
  869. #define vlmn vec3
  870.     if ( !pcie->caches.skipABC )
  871.       cie_lookup_map3(&vabc /*&vlmn*/, &pcie->caches.DecodeABC[0],
  872.               "Decode/MatrixABC");
  873. #undef vabc
  874.     cie_remap_finish(&vlmn, pconc, pis);
  875. #undef vlmn
  876.     return 0;
  877. }
  878.  
  879. /* Render a CIEBasedA color. */
  880. private int
  881. gx_concretize_CIEA(const gs_client_color *pc, const gs_color_space *pcs,
  882.   frac *pconc, const gs_imager_state *pis)
  883. {    const gs_cie_a *pcie = pcs->params.a;
  884.     cie_cached_value a = float2cie_cached(pc->paint.values[0]);
  885.     cie_cached_vector3 vlmn;
  886.  
  887.     if_debug1('c', "[c]concretize CIEA %g\n", pc->paint.values[0]);
  888.  
  889.     /* Apply DecodeA and MatrixA. */
  890.     vlmn = lookup_value(a, &pcie->caches.DecodeA);
  891.     return cie_remap_finish(&vlmn, pconc, pis);
  892. }
  893.  
  894. /* Common rendering code. */
  895. /* Return 3 if RGB, 4 if CMYK. */
  896. private int near
  897. cie_remap_finish(const cie_cached_vector3 *plmn, frac *pconc,
  898.   const gs_imager_state *pis)
  899. {    const gs_cie_render *pcie = pis->cie_render;
  900.     const gx_cie_joint_caches *pjc = pis->cie_joint_caches;
  901.     const gs_const_string *table;
  902.     cie_cached_vector3 vec3;
  903.     int tabc[3];        /* indices for final EncodeABC lookup */
  904.  
  905.     if ( pcie == 0 )
  906.       {    /* No rendering has been defined yet. */
  907.         /* Just return black. */
  908.         pconc[0] = pconc[1] = pconc[2] = frac_0;
  909.         return 3;
  910.       }
  911.  
  912.     /* Apply DecodeLMN, MatrixLMN(decode), and MatrixPQR. */
  913. #define vlmn vec3
  914.     vlmn = *plmn;
  915. #define vpqr vec3
  916.     if ( !pjc->skipLMN )
  917.       cie_lookup_map3(&vlmn /*&vpqr*/, &pjc->DecodeLMN[0],
  918.               "Decode/MatrixLMN+MatrixPQR");
  919. #undef vlmn
  920.  
  921.     /* Apply TransformPQR, MatrixPQR', and MatrixLMN(encode). */
  922. #define vlmn vec3
  923.     if ( !pjc->skipPQR )
  924.       cie_lookup_map3(&vpqr /*&vlmn*/, &pjc->TransformPQR[0],
  925.               "Transform/Matrix'PQR+MatrixLMN");
  926. #undef vpqr
  927.  
  928.     /* Apply EncodeLMN and MatrixABC(encode). */
  929. #define vabc vec3
  930.     cie_lookup_map3(&vlmn /*&vabc*/, &pcie->caches.EncodeLMN[0],
  931.             "EncodeLMN+MatrixABC");
  932. #undef vlmn
  933.     /* MatrixABCEncode includes the scaling of the EncodeABC */
  934.     /* cache index. */
  935. #define set_tabc(i, t)\
  936.   set_restrict_index(tabc[i],\
  937.              cie_cached2int(vabc.t - pcie->EncodeABC_base[i],\
  938.                     _cie_interpolate_bits),\
  939.              gx_cie_cache_size << _cie_interpolate_bits)
  940.     set_tabc(0, u);
  941.     set_tabc(1, v);
  942.     set_tabc(2, w);
  943.     table = pcie->RenderTable.lookup.table;
  944.     if ( table == 0 )
  945.     {    /* No further transformation. */
  946.         /* The final mapping step includes both restriction to */
  947.         /* the range [0..1] and conversion to fracs. */
  948. #define eabc(i)\
  949.   cie_interpolate_fracs(pcie->caches.EncodeABC[i].fracs.values, tabc[i])
  950.         pconc[0] = eabc(0);
  951.         pconc[1] = eabc(1);
  952.         pconc[2] = eabc(2);
  953. #undef eabc
  954.         return 3;
  955.     }
  956.     else
  957.     {    /* Use the RenderTable. */
  958.         int m = pcie->RenderTable.lookup.m;
  959. #define rt_lookup(j, i) pcie->caches.RenderTableT[j].fracs.values[i]
  960. #ifdef CIE_RENDER_TABLE_INTERPOLATE
  961.  
  962.         /* The final mapping step includes restriction to the */
  963.         /* ranges [0..dims[c]] as ints with interpolation bits. */
  964.         fixed rfix[3];
  965.  
  966. #define eabc(i)\
  967.   cie_interpolate_fracs(pcie->caches.EncodeABC[i].ints.values, tabc[i])
  968. #define fabc(i)\
  969.   (eabc(i) << (_fixed_shift - _cie_interpolate_bits))
  970.         rfix[0] = fabc(0);
  971.         rfix[1] = fabc(1);
  972.         rfix[2] = fabc(2);
  973.         if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%g,%g,%g\n",
  974.               cie_cached2float(vabc.u), cie_cached2float(vabc.v),
  975.               cie_cached2float(vabc.w), fixed2float(rfix[0]),
  976.               fixed2float(rfix[1]), fixed2float(rfix[2]));
  977.         gx_color_interpolate_linear(rfix, &pcie->RenderTable.lookup,
  978.                         pconc);
  979.         if_debug3('c', "[c]  interpolated => %g,%g,%g\n",
  980.               frac2float(pconc[0]), frac2float(pconc[1]),
  981.               frac2float(pconc[2]));
  982.         if ( !pcie->caches.RenderTableT_is_identity )
  983.           {    /* Map the interpolated values. */
  984. #define frac2cache_index(v) frac2bits(v, gx_cie_log2_cache_size)
  985.             pconc[0] = rt_lookup(0, frac2cache_index(pconc[0]));
  986.             pconc[1] = rt_lookup(1, frac2cache_index(pconc[1]));
  987.             pconc[2] = rt_lookup(2, frac2cache_index(pconc[2]));
  988.             if ( m > 3 )
  989.               pconc[3] = rt_lookup(3, frac2cache_index(pconc[3]));
  990. #undef frac2cache_index
  991.           }
  992.  
  993. #else                /* !CIE_RENDER_TABLE_INTERPOLATE */
  994.  
  995.         /* The final mapping step includes restriction to the */
  996.         /* ranges [0..dims[c]], plus scaling of the indices */
  997.         /* in the strings. */
  998. #define ri(i)\
  999.   pcie->caches.EncodeABC[i].ints.values[tabc[i] >> _cie_interpolate_bits]
  1000.         int ia = ri(0);
  1001.         int ib = ri(1);        /* pre-multiplied by m * NC */
  1002.         int ic = ri(2);        /* pre-multiplied by m */
  1003.         const byte *prtc = table[ia].data + ib + ic;
  1004.             /* (*pcie->RenderTable.T)(prtc, m, pcie, pconc); */
  1005.  
  1006.         if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%d,%d,%d\n",
  1007.               cie_cached2float(vabc.u), cie_cached2float(vabc.v),
  1008.               cie_cached2float(vabc.w), ia, ib, ic);
  1009.         if ( pcie->caches.RenderTableT_is_identity )
  1010.           {    pconc[0] = byte2frac(prtc[0]);
  1011.             pconc[1] = byte2frac(prtc[1]);
  1012.             pconc[2] = byte2frac(prtc[2]);
  1013.             if ( m > 3 )
  1014.               pconc[3] = byte2frac(prtc[3]);
  1015.           }
  1016.         else
  1017.           {
  1018. #if gx_cie_log2_cache_size == 8
  1019. #  define byte2cache_index(b) (b)
  1020. #else
  1021. # if gx_cie_log2_cache_size > 8
  1022. #  define byte2cache_index(b)\
  1023.     ( ((b) << (gx_cie_log2_cache_size - 8)) +\
  1024.       ((b) >> (16 - gx_cie_log2_cache_size)) )
  1025. # else    /* < 8 */
  1026. #  define byte2cache_index(b) ((b) >> (8 - gx_cie_log2_cache_size))
  1027. # endif
  1028. #endif
  1029.             pconc[0] = rt_lookup(0, byte2cache_index(prtc[0]));
  1030.             pconc[1] = rt_lookup(1, byte2cache_index(prtc[1]));
  1031.             pconc[2] = rt_lookup(2, byte2cache_index(prtc[2]));
  1032.             if ( m > 3 )
  1033.               pconc[3] = rt_lookup(3, byte2cache_index(prtc[3]));
  1034. #undef byte2cache_index
  1035.           }
  1036.  
  1037. #endif                /* !CIE_RENDER_TABLE_INTERPOLATE */
  1038. #undef ri
  1039. #undef rt_lookup
  1040.         return m;
  1041.     }
  1042. }
  1043.  
  1044. /* ================ Utilities ================ */
  1045.  
  1046. #define if_debug_vector3(str, vec)\
  1047.   if_debug4('c', "%s[%g %g %g]\n", str, vec->u, vec->v, vec->w)
  1048. #define if_debug_matrix3(str, mat)\
  1049.   if_debug10('c', "%s[%g %g %g / %g %g %g / %g %g %g]\n", str,\
  1050.     mat->cu.u, mat->cu.v, mat->cu.w, mat->cv.u, mat->cv.v, mat->cv.w,\
  1051.     mat->cw.u, mat->cw.v, mat->cw.w)
  1052.  
  1053. /* Multiply a vector by a matrix. */
  1054. /* Note that we are computing M * V where v is a column vector. */
  1055. private void near
  1056. cie_mult3(const gs_vector3 *in, register const gs_matrix3 *mat,
  1057.   gs_vector3 *out)
  1058. {    if_debug_vector3("[c]mult", in);
  1059.     if_debug_matrix3("    *", mat);
  1060.     {    float u = in->u, v = in->v, w = in->w;
  1061.         out->u = (u * mat->cu.u) + (v * mat->cv.u) + (w * mat->cw.u);
  1062.         out->v = (u * mat->cu.v) + (v * mat->cv.v) + (w * mat->cw.v);
  1063.         out->w = (u * mat->cu.w) + (v * mat->cv.w) + (w * mat->cw.w);
  1064.     }
  1065.     if_debug_vector3("    =", out);
  1066. }
  1067.  
  1068. /* Multiply two matrices.  We assume the result is not an alias for */
  1069. /* either of the operands.  Note that the composition of the transformations */
  1070. /* M1 followed by M2 is M2 * M1, not M1 * M2.  (See gscie.h for details.) */
  1071. private void near
  1072. cie_matrix_mult3(const gs_matrix3 *ma, const gs_matrix3 *mb, gs_matrix3 *mc)
  1073. {    if_debug_matrix3("[c]matrix_mult", ma);
  1074.     if_debug_matrix3("             *", mb);
  1075.     cie_mult3(&mb->cu, ma, &mc->cu);
  1076.     cie_mult3(&mb->cv, ma, &mc->cv);
  1077.     cie_mult3(&mb->cw, ma, &mc->cw);
  1078.     cie_matrix_init(mc);
  1079.     if_debug_matrix3("             =", mc);
  1080. }
  1081.  
  1082. /* Invert a matrix. */
  1083. /* The output must not be an alias for the input. */
  1084. private void near
  1085. cie_invert3(register const gs_matrix3 *in, register gs_matrix3 *out)
  1086. {    /* This is a brute force algorithm; maybe there are better. */
  1087.     /* We label the array elements */
  1088.     /*   [ A B C ]   */
  1089.     /*   [ D E F ]   */
  1090.     /*   [ G H I ]   */
  1091. #define A cu.u
  1092. #define B cv.u
  1093. #define C cw.u
  1094. #define D cu.v
  1095. #define E cv.v
  1096. #define F cw.v
  1097. #define G cu.w
  1098. #define H cv.w
  1099. #define I cw.w
  1100.     double coA = in->E * in->I - in->F * in->H; 
  1101.     double coB = in->F * in->G - in->D * in->I; 
  1102.     double coC = in->D * in->H - in->E * in->G;
  1103.     double det = in->A * coA + in->B * coB + in->C * coC;
  1104.     if_debug_matrix3("[c]invert", in);
  1105.     out->A = coA / det;
  1106.     out->D = coB / det;
  1107.     out->G = coC / det;
  1108.     out->B = (in->C * in->H - in->B * in->I) / det;
  1109.     out->E = (in->A * in->I - in->C * in->G) / det;
  1110.     out->H = (in->B * in->G - in->A * in->H) / det;
  1111.     out->C = (in->B * in->F - in->C * in->E) / det;
  1112.     out->F = (in->C * in->D - in->A * in->F) / det;
  1113.     out->I = (in->A * in->E - in->B * in->D) / det;
  1114.     if_debug_matrix3("        =", out);
  1115. #undef A
  1116. #undef B
  1117. #undef C
  1118. #undef D
  1119. #undef E
  1120. #undef F
  1121. #undef G
  1122. #undef H
  1123. #undef I
  1124.     out->is_identity = in->is_identity;
  1125. }
  1126.  
  1127. /* Look up 3 values in a cache, with cached post-multiplication. */
  1128. private void near
  1129. cie_lookup_mult3(cie_cached_vector3 *pvec, const gx_cie_vector_cache *pc /*[3]*/)
  1130. {
  1131.     /****** Interpolating at intermediate stages doesn't seem to ******/
  1132.     /****** make things better, and slows things down, so....    ******/
  1133. #ifdef CIE_INTERPOLATE_INTERMEDIATE
  1134.     /* Interpolate between adjacent cache entries. */
  1135.     /* This is expensive! */
  1136. #ifdef CIE_CACHE_USE_FIXED
  1137. #  define lookup_interpolate_between(v0, v1, i, ftemp)\
  1138.      cie_interpolate_between(v0, v1, i)
  1139. #else
  1140.     float ftu, ftv, ftw;
  1141. #  define lookup_interpolate_between(v0, v1, i, ftemp)\
  1142.      ((v0) + ((v1) - (v0)) *\
  1143.       ((ftemp = float_rshift(i, _cie_interpolate_bits)), ftemp - (int)ftemp))
  1144. #endif
  1145.  
  1146.     cie_cached_value iu =
  1147.       lookup_index(pvec->u, pc, _cie_interpolate_bits);
  1148.     const cie_cached_vector3 *pu =
  1149.       &pc[0].vecs.values[(int)cie_cached_rshift(iu,
  1150.                             _cie_interpolate_bits)];
  1151.     const cie_cached_vector3 *pu1 =
  1152.       (iu >= (gx_cie_cache_size - 1) << _cie_interpolate_bits ?
  1153.        pu : pu + 1);
  1154.  
  1155.     cie_cached_value iv =
  1156.       lookup_index(pvec->v, pc + 1, _cie_interpolate_bits);
  1157.     const cie_cached_vector3 *pv =
  1158.       &pc[1].vecs.values[(int)cie_cached_rshift(iv,
  1159.                             _cie_interpolate_bits)];
  1160.     const cie_cached_vector3 *pv1 =
  1161.       (iv >= (gx_cie_cache_size - 1) << _cie_interpolate_bits ?
  1162.        pv : pv + 1);
  1163.  
  1164.     cie_cached_value iw =
  1165.       lookup_index(pvec->w, pc + 2, _cie_interpolate_bits);
  1166.     const cie_cached_vector3 *pw =
  1167.       &pc[2].vecs.values[(int)cie_cached_rshift(iw,
  1168.                             _cie_interpolate_bits)];
  1169.     const cie_cached_vector3 *pw1 =
  1170.       (iw >= (gx_cie_cache_size - 1) << _cie_interpolate_bits ?
  1171.        pw : pw + 1);
  1172.  
  1173.     pvec->u = lookup_interpolate_between(pu->u, pu1->u, iu, ftu) +
  1174.       lookup_interpolate_between(pv->u, pv1->u, iv, ftv) +
  1175.       lookup_interpolate_between(pw->u, pw1->u, iw, ftw);
  1176.     pvec->v = lookup_interpolate_between(pu->v, pu1->v, iu, ftu) +
  1177.       lookup_interpolate_between(pv->v, pv1->v, iv, ftv) +
  1178.       lookup_interpolate_between(pw->v, pw1->v, iw, ftw);
  1179.     pvec->w = lookup_interpolate_between(pu->w, pu1->w, iu, ftu) +
  1180.       lookup_interpolate_between(pv->w, pv1->w, iv, ftv) +
  1181.       lookup_interpolate_between(pw->w, pw1->w, iw, ftw);
  1182. #else
  1183.     const cie_cached_vector3 *pu = &lookup_value(pvec->u, pc);
  1184.     const cie_cached_vector3 *pv = &lookup_value(pvec->v, pc + 1);
  1185.     const cie_cached_vector3 *pw = &lookup_value(pvec->w, pc + 2);
  1186.     pvec->u = pu->u + pv->u + pw->u;
  1187.     pvec->v = pu->v + pv->v + pw->v;
  1188.     pvec->w = pu->w + pv->w + pw->w;
  1189. #endif
  1190. }
  1191.  
  1192. /* Set the is_identity flag that accelerates multiplication. */
  1193. private void near
  1194. cie_matrix_init(register gs_matrix3 *mat)
  1195. {    mat->is_identity =
  1196.       mat->cu.u == 1.0 && is_fzero2(mat->cu.v, mat->cu.w) &&
  1197.         mat->cv.v == 1.0 && is_fzero2(mat->cv.u, mat->cv.w) &&
  1198.           mat->cw.w == 1.0 && is_fzero2(mat->cw.u, mat->cw.v);
  1199. }
  1200.